// 包含计算温湿度的模块
#include "dht11.h"

// 定义用于计算温湿度的变量
dht11 DHT11;

// 定义温度引脚
#define tempPin 2

// 定义土壤湿度引脚
#define humidityPin 3

// 定义光照引脚
#define lightPin 4

// 定义浇水引脚
#define waterPin 5

// 定义温度变量
int tempValue = 0;

// 定义土壤湿度变量
int humidityValue = 0;

// 定义光照变量
int lightValue = 0;

// 定义浇水变量
int waterValue = 0;

// 定义字符串接收缓冲区
String data = "";
// 定义发送数据的时间间隔
int data_send_interraval = 2000;
int data_send_counter = 0;

/*
   获取温度
*/
void getTemp() {
  // 读取温度并判断是否读取成功
  int chk = DHT11.read(2);
  if (DHTLIB_OK == chk) {
    tempValue = (float)DHT11.temperature;
  } else {
    tempValue = 0;
  }
}

/*
   获取湿度
*/
void getHumidity() {
  // 空气中最大值为960,完全入水最小值为660,将值归一化到0-100
  humidityValue = analogRead(waterPin);
  humidityValue = (960 - humidityValue);
  if (humidityValue < 0) {
    humidityValue = 0;
  }
  humidityValue = humidityValue / 3;
}

/*
   设置光照
*/
void setLight() {
  if (lightValue) {
    digitalWrite(lightPin, HIGH);
  } else {
    digitalWrite(lightPin, LOW);
  }
}

/*
   设置浇水
*/
void setWater() {
  if(!waterValue) {
    digitalWrite(waterPin, HIGH);
  } else {
    digitalWrite(waterPin, LOW);
  }
}

/*采集数据并发送数据*/
void sampleAndSendData() {
  getTemp();
  getHumidity();
  // 采用json数据包的方式将数据发送出去
  Serial.print("{\"temp\":");
  Serial.print(tempValue);
  Serial.print(",\"humidity\":");
  Serial.print(humidityValue);
  Serial.print(",\"water\":");
  Serial.print(waterValue);
  Serial.print(",\"light\":");
  Serial.print(lightValue);
  Serial.println("}");
}

/*解析上位机发送的json数据并进行相应的设置*/
void resolveJsonAndSetHardWare(String json) {
  // 完整的json数据包格式
  // {'L':0} {'P':1}

  // 处理照明
  if (json[2] == 'L')
  {
    if (json[5] == '0') {
      lightValue = 0;
    } else {
      lightValue = 1;
    }
    setLight();
  } else if (json[2] == 'P') { // 处理交水
    if (json[5] == '0') {
      waterValue = 0;
    } else {
      waterValue = 1;
    }
    setWater();
  }
}

void setup()
{
  // [0] 初始化串口
  Serial.begin(115200);

  // [1] 初始化其它相关的引脚
  pinMode(humidityPin, INPUT);
  pinMode(lightPin, OUTPUT);
  pinMode(waterPin, OUTPUT);

  // [2] 设置默认状态
  setLight();
  setWater();
}

void loop()
{
  // [0] 获取控制状态信息并进行相应的数据解析
  while (Serial.available() > 0) {
    data += char(Serial.read());
    delay(2);
  }
  // [1] json 数据接收完成
  if (data[0] == '{' && data[6] == '}') {
    resolveJsonAndSetHardWare(data);
    data = "";
  }

  // [2] 判断是否到了发送数据的时间
  if (data_send_interraval == data_send_counter) {
    // (0) 采集一次数据并发送数据
    sampleAndSendData();
    data_send_counter = 0;
  } else {
    data_send_counter += 10;
  }
  // 适当延时避免数据缓冲区溢出
  delay(10);
}
